#include "Vertex.h"



///<************************************************************************************************************>
///<************************************* region CONSTANTS DEFINITION ******************************************>
///<************************************************************************************************************>

const CICore::Vertex CICore::Vertex::ORIGIN = Vertex (0, 0, 0);
/***************************************************************************************************************
************************************** endregion CONSTANTS DEFINITION ******************************************
****************************************************************************************************************/







/// <summary>
/// Constructor
/// </summary>
/// <param name="vx"> The x-axis value </param>
/// <param name="vy"> The y-axis value </param>
/// <param name="vz"> The z-axis value </param>
CICore::Vertex::Vertex (const float vx, const float vy, const float vz)
: x (vx), y (vy), z (vz), selected (true), visible (true) {}

/// <summary>
/// Constructor
/// </summary>
/// <param name="v"> The vertex from which retrieve information </param>
CICore::Vertex::Vertex (const Vertex& v) : x (v.x), y (v.y), z (v.z), selected (v.selected), visible (true) {}


/// <summary>
/// Constructor
/// </summary>
/// <param name="p"> The point from which retrieve information </param>
CICore::Vertex::Vertex (const Point& p) : x (p.x), y (p.y), z (p.z), selected (true), visible (true) {}


/// <summary>
/// Destructor
/// </summary>
CICore::Vertex::~Vertex() {}







///<************************************************************************************************************>
///<**************************************** region Utility Methods ********************************************>
///<************************************************************************************************************>

void CICore::Vertex::Transform (const CICore::Matrix& m) {
    Vertex v;

    //Computing the transformation
    v.x = x * m.elements[ 0 ] + y * m.elements[ 4 ] + z * m.elements[ 8 ] + m.elements[ 12 ];
    v.y = x * m.elements[ 1 ] + y * m.elements[ 5 ] + z * m.elements[ 9 ] + m.elements[ 13 ];
    v.z = x * m.elements[ 2 ] + y * m.elements[ 6 ] + z * m.elements[ 10 ] + m.elements[ 14 ];    

    //Setting the new vertex's coordinates
    x = v.x;
    y = v.y;
    z = v.z;
}

CICore::Vertex* CICore::Vertex::MidPoint (const CICore::Vertex* v1, const CICore::Vertex* v2) {
    float x = (v1->x + v2->x) / 2.0f;
    float y = (v1->y + v2->y) / 2.0f;
    float z = (v1->z + v2->z) / 2.0f;

    return new Vertex (x, y, z);
}
/***************************************************************************************************************
******************************************* endregion Utility Methods ******************************************
****************************************************************************************************************/











///<************************************************************************************************************>
///<******************************* region BASIC VERTEX's UNARY OPERATIONS *************************************>
///<************************************************************************************************************>

/// <summary>
/// Postfix increment
/// </summary>
/// <param name="v"> The vertex to be modified </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::operator ++ (Vertex& v, int) {
    v.x++;
    v.y++;
    v.z++;

    return v;
}

/// <summary>
/// Prefix increment
/// </summary>
/// <param name="v"> The vertex to be modified </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::operator ++ (Vertex& v) {
    ++(v.x);
    ++(v.y);
    ++(v.z);

    return v;
}

/// <summary>
/// Postfix decrement
/// </summary>
/// <param name="v"> The vertex to be modified </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::operator -- (Vertex& v, int) {
    v.x--;
    v.y--;
    v.z--;

    return v;
}

/// <summary>
/// Prefix decrement
/// </summary>
/// <param name="v"> The vertex to be modified </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::operator -- (Vertex& v) {
    --(v.x);
    --(v.y);
    --(v.z);

    return v;
}

/// <summary>
/// Basic Assignment
/// </summary>
/// <param name="p"> The point from which retrieve information </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::Vertex::operator = (Point& p) {
    x = p.x;
    y = p.y;
    z = p.z;

    return (*this);
}
/***************************************************************************************************************
********************************** endregion BASIC VERTEX's UNARY OPERATIONS ***********************************
****************************************************************************************************************/









///<************************************************************************************************************>
///<******************************* region BASIC VERTEX's BINARY OPERATIONS ************************************>
///<************************************************************************************************************>

/// <summary>
/// Equal to operator between two vertices
/// </summary>
/// <param name="a"> The first vertex </param>
/// <param name="b"> The second vertex </param>
/// <returns> A boolean to indicate if a is equal to b </returns>
bool CICore::operator == (const Vertex& a, const Vertex& b) {
    return (a.x==b.x && a.y==b.y && a.z==b.z);
}

/// <summary>
/// Sum between two vertices
/// </summary>
/// <param name="a"> The first vertex </param>
/// <param name="b"> The second vertex </param>
/// <returns> The sum between the two vertices </returns>
CICore::Vertex CICore::operator + (const Vertex& a, const Vertex& b) {
    return Vertex(a.x+b.x, a.y+b.y, a.z+b.z);
}

/// <summary>
/// Assignment by addition between two vertices
/// </summary>
/// <param name="a"> The vertex to be modified </param>
/// <param name="b"> The vertex to be added </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::operator += (Vertex& a, const Vertex& b) {
    a.x += b.x;
    a.y += b.y;
    a.z += b.z;

    return a;
}

/// <summary>
/// Difference between two vertices
/// </summary>
/// <param name="a"> The first vertex </param>
/// <param name="b"> The second vertex </param>
/// <returns> The difference between the two vertices </returns>
CICore::Vertex CICore::operator - (const Vertex& a, const Vertex& b) {
    return Vertex(a.x-b.x, a.y-b.y, a.z-b.z);
}

/// <summary>
/// Assignment by substraction between two vertices
/// </summary>
/// <param name="a"> The vertex to be modified </param>
/// <param name="b"> The vertex to be substracted </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::operator -= (Vertex& a, const Vertex& b) {
    a.x -= b.x;
    a.y -= b.y;
    a.z -= b.z;

    return a;
}

/// <summary>
/// Product between two vertices
/// </summary>
/// <param name="a"> The multiplicand vertex </param>
/// <param name="b"> The multiplier vertex </param>
/// <returns> The product between the two vertices </returns>
CICore::Vertex CICore::operator * (const Vertex& a, const Vertex& b) {
    return Vertex(a.x*b.x, a.y*b.y, a.z*b.z);
}

/// <summary>
/// Assignment by multiplication between two vertices
/// </summary>
/// <param name="a"> The vertex to be modified </param>
/// <param name="b"> The multiplier vertex </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::operator *= (Vertex& a, const Vertex& b) {
    a.x *= b.x;
    a.y *= b.y;
    a.z *= b.z;

    return a;
}

/// <summary>
/// Quotient between two vertices
/// </summary>
/// <param name="a"> The dividend vertex </param>
/// <param name="b"> The divisor vertex </param>
/// <returns> The quotient between the two vertices </returns>
CICore::Vertex CICore::operator / (const Vertex& a, const Vertex& b) {
    return Vertex(a.x/b.x, a.y/b.y, a.z/b.z);
}

/// <summary>
/// Assignment by division between two vertices
/// </summary>
/// <param name="a"> The vertex to be modified </param>
/// <param name="b"> The divisor vertex </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::operator /= (Vertex& a, const Vertex& b) {
    a.x /= b.x;
    a.y /= b.y;
    a.z /= b.z;

    return a;
}


/// <summary>
/// Sum between a vertex and a float value
/// </summary>
/// <param name="a"> The vertex </param>
/// <param name="f"> The float value to be added </param>
/// <returns> The sum between the vertex and the float value </returns>
CICore::Vertex CICore::operator + (const Vertex& a, const float f) {
    return Vertex(a.x+f, a.y+f, a.z+f);
}

/// <summary>
/// Assignment by addition between a vertex and a float value
/// </summary>
/// <param name="a"> The vertex to be modified </param>
/// <param name="b"> The float value to be added </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::operator += (Vertex& a, const float f) {
    a.x += f;
    a.y += f;
    a.z += f;

    return a;
}

/// <summary>
/// Difference between a vertex and a float value
/// </summary>
/// <param name="a"> The vertex </param>
/// <param name="b"> The float value to be substracted </param>
/// <returns> The difference between the vertex and the float value </returns>
CICore::Vertex CICore::operator - (const Vertex& a, const float f) {
    return Vertex(a.x-f, a.y-f, a.z-f);
}

/// <summary>
/// Assignment by substraction between a vertex and a float value
/// </summary>
/// <param name="a"> The vertex to be modified </param>
/// <param name="b"> The float value to be substracted </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::operator -= (Vertex& a, const float f) {
    a.x -= f;
    a.y -= f;
    a.z -= f;

    return a;
}

/// <summary>
/// Product between a vertex and a float value
/// </summary>
/// <param name="a"> The multiplicand vertex </param>
/// <param name="b"> The multiplier float value </param>
/// <returns> The product between the and the float value </returns>
CICore::Vertex CICore::operator * (const Vertex& a, const float f) {
    return Vertex(a.x*f, a.y*f, a.z*f);
}

/// <summary>
/// Assignment by multiplication between a vertex and a float value
/// </summary>
/// <param name="a"> The vertex to be modified </param>
/// <param name="b"> The multiplier float value </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::operator *= (Vertex& a, const float f) {
    a.x *= f;
    a.y *= f;
    a.z *= f;

    return a;
}

/// <summary>
/// Quotient between a vertex and a float value
/// </summary>
/// <param name="a"> The dividend vertex </param>
/// <param name="b"> The divisor float value </param>
/// <returns> The quotient between the and the float value </returns>
CICore::Vertex CICore::operator / (const Vertex& a, const float f) {
    return Vertex(a.x/f, a.y/f, a.z/f);
}

/// <summary>
/// Assignment by division between a vertex and a float value
/// </summary>
/// <param name="a"> The vertex to be modified </param>
/// <param name="b"> The divisor float value </param>
/// <returns> A reference of the vertex modified </returns>
CICore::Vertex& CICore::operator /= (Vertex& a, const float f) {
    a.x /= f;
    a.y /= f;
    a.z /= f;

    return a;
}
/***************************************************************************************************************
********************************** endregion BASIC VERTEX's BINARY OPERATIONS **********************************
****************************************************************************************************************/
